use std::time::Duration;
use reqwest::{Client as ReqwestClient};
use rustcloud_core::{Request as ServiceRequest, Response as ServiceResponse, ServiceError};
use rustcloud_core::http_client::{HttpClientConfig, HttpClientFactory};

/// HTTP客户端配置（重新导出统一配置）
pub type ClientConfig = HttpClientConfig;

/// HTTP客户端封装
pub struct HttpClient {
    client: ReqwestClient,
    config: ClientConfig,
}

impl HttpClient {
    /// 使用统一的工厂方法创建客户端
    pub fn new(config: ClientConfig) -> Result<Self, ServiceError> {
        let client = HttpClientFactory::create_reqwest_client(&config)
            .map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        Ok(Self { client, config })
    }
    
    /// 使用预定义的传输层配置创建客户端
    pub fn new_transport() -> Result<Self, ServiceError> {
        let config = HttpClientConfig::for_transport();
        Self::new(config)
    }

    pub async fn send_request(&self, request: ServiceRequest) -> Result<ServiceResponse, ServiceError> {
        let url = format!("{}{}", request.service_name, request.path);
        
        let mut reqwest_request = match request.method.as_str().to_uppercase().as_str() {
            "GET" => self.client.get(&url),
            "POST" => self.client.post(&url),
            "PUT" => self.client.put(&url),
            "DELETE" => self.client.delete(&url),
            "PATCH" => self.client.patch(&url),
            method => return Err(ServiceError::ConfigurationError(format!("Unsupported HTTP method: {}", method))),
        };

        for (key, value) in &request.headers {
            reqwest_request = reqwest_request.header(key, value);
        }

        for (key, value) in &request.query_params {
            reqwest_request = reqwest_request.query(&[(key, value)]);
        }

        if let Some(body) = request.body {
            reqwest_request = reqwest_request.body(body);
        }

        let response = reqwest_request.send().await.map_err(|e| ServiceError::NetworkError(e.to_string()))?;
        let status = response.status().as_u16();
        let headers = response.headers()
            .iter()
            .map(|(k, v)| (k.to_string(), v.to_str().unwrap_or("").to_string()))
            .collect();
        let body = response.bytes().await.map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        Ok(ServiceResponse {
            status,
            headers,
            body: Some(body.to_vec()),
        })
    }

    pub async fn retry_request(&self, request: ServiceRequest) -> Result<ServiceResponse, ServiceError> {
        let mut attempts = 0;
        loop {
            match self.send_request(request.clone()).await {
                Ok(response) => return Ok(response),
                Err(_) if attempts < self.config.retry_count => {
                    attempts += 1;
                    tokio::time::sleep(self.config.retry_delay).await;
                }
                Err(e) => return Err(e),
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use rustcloud_core::Request as ServiceRequest;
    use wiremock::{MockServer, Mock, ResponseTemplate};
    use wiremock::matchers::{method, path};

    #[tokio::test]
    async fn test_client_creation() {
        let config = ClientConfig::default();
        let client = HttpClient::new(config).unwrap();
        assert!(!client.config.timeout.is_zero());
    }

    #[tokio::test]
    async fn test_send_request() {
        let mock_server = MockServer::start().await;
        Mock::given(method("GET"))
            .and(path("/test"))
            .respond_with(ResponseTemplate::new(200).set_body_string("Hello, World!"))
            .mount(&mock_server)
            .await;

        let config = ClientConfig::default();
        let client = HttpClient::new(config).unwrap();

        let mut request = ServiceRequest::new("test-service", "GET", "/test");
        request.service_name = mock_server.uri();

        let response = client.send_request(request).await.unwrap();
        assert_eq!(response.status, 200);
        assert_eq!(response.body.unwrap(), b"Hello, World!");
    }
}